/*
 * Thread.cc
 *
 *  Created on: 2021年4月5日
 *      Author: san
 */

#include "Thread.h"
#include <assert.h>
#include <errno.h>
#include <linux/unistd.h>
#include <cstdint>
#include <cstdio>
#include <sys/prctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <memory.h>
#include "CurrentThread.h"

namespace san {

namespace CurrentThread
{
	__thread int t_cachedTid = 0;
	__thread char t_tidString[32];
	__thread int t_tidStringLength = 6;
	__thread const char* t_threadName = "default";
} /* namespace CurrentThread */

//using san::CurrentThread::t_cachedTid;
//using san::CurrentThread::t_tidString;
//using san::CurrentThread::t_tidStringLength;
//using san::CurrentThread::t_threadName;


pid_t gettid() { return static_cast<pid_t>(::syscall(SYS_gettid)); }

void CurrentThread::cacheTid()
{
	if (t_cachedTid == 0)
	{
		t_cachedTid = gettid();
		t_tidStringLength = snprintf(t_tidString, sizeof t_tidString, "%5d", t_cachedTid);
	}
}

// 为了在线程中保留name, tid 这些数据
struct ThreadData {
	typedef Thread::ThreadFunc ThreadFunc;
	ThreadFunc threadFunc_;
	std::string name_;
	pid_t *tid_;
	CountDownLatch *latch_;

	ThreadData(const ThreadFunc &func, const std::string &name, pid_t *tid, CountDownLatch *latch)
		: threadFunc_(func), name_(name), tid_(tid), latch_(latch)
	{
	}

	void runInThread()
	{
		*tid_ = CurrentThread::tid();
		tid_ = NULL;
		latch_->countDown();
		latch_ = NULL;

		CurrentThread::t_threadName = name_.empty() ? "Thread" : name_.c_str();
		prctl(PR_SET_NAME, CurrentThread::t_threadName);

		threadFunc_();
		CurrentThread::t_threadName = "finished";
	}
};

void *startThread(void *obj)
{
	ThreadData *data = static_cast<ThreadData*>(obj);
	data->runInThread();
	delete data;
	return NULL;
}

Thread::Thread(const ThreadFunc &func, const std::string &n)
	: started_(false),
	  joined_(false),
	  pthreadId_(0),
	  tid_(0),
	  threadFunc_(func),
	  name_(n),
	  latch_(1)
{
	setDefaultName();
}

Thread::~Thread()
{
	if (started_ && !joined_)
		pthread_detach(pthreadId_);    // 将线程设置为detach
}

void Thread::setDefaultName()
{
	if (name_.empty())
	{
		char buf[32];
		snprintf(buf, sizeof buf, "Thread");
		name_ = buf;
	}
}

void Thread::start()
{
	assert(!started_);
	started_ = true;
	ThreadData *data = new ThreadData(threadFunc_, name_, &tid_, &latch_);
	if (pthread_create(&pthreadId_, NULL, &startThread,  data))
	{
		// 创建线程失败， pthread_create成功返回0
		started_ = false;
		delete data;         // or no delete?
	}
	else
	{
		latch_.wait();
		assert(tid_ > 0);
	}
}

int Thread::join()
{
	assert(started_);
	assert(!joined_);
	joined_ = true;
	return  pthread_join(pthreadId_, NULL);
}

} /* namespace san */
